#pragma once
#include "StreamReceiver.h"
#include "StreamSource.h"

#include "playCommon.hh"
#include "BasicUsageEnvironment.hh"
#include "GroupsockHelper.hh"

#include "qosMeasurementRecord.h"

#ifdef SUPPORT_REAL_RTSP
#include "../RealRTSP/include/RealRTSP.hh"
#endif

#if defined(__WIN32__) || defined(_WIN32)
#define snprintf _snprintf
#else
#include <signal.h>
#define USE_SIGNALS 1
#endif

#define RTSP_MODE 0
#define RTSP_TCP_MODE 1
#define RTSP_OVER_HTTP_MODE 2

#define MAX_QUALITY_LEVEL	3

class CIPCameraStreamReceiver : public CStreamReceiver
{
public:
	CIPCameraStreamReceiver(int int_stream_id);
	~CIPCameraStreamReceiver(void);

public:
	virtual void Run(void* This);
	void SetRTSPServerURI(char* rtspServerUri);

private:
	int m_mode;
	char m_rtspServerUri[512];

public:
	BOOL	m_isStoped;			// stop flag;
	BOOL	m_isStarted;		// start flag
	BOOL	m_needShutdown;		// shutdown flag

	char profileLevelID[10];
	char spsParameter[1024];	// SPS Parameter

	//in playcommon.cpp
	void usage();
	// Forward function definitions:
	void setupStreams();
	void startPlayingStreams();
	void tearDownStreams();
	void closeMediaSinks();
	void shutdown(int exitCode = 1);
	void signalHandlerShutdown(int sig);
	void beginQOSMeasurement();
	void printQOSData(int exitCode);


	char const* progName;
	UsageEnvironment* env;
	Medium* ourClient;
	MediaSession* session;
	TaskToken sessionTimerTask;
	TaskToken arrivalCheckTimerTask;
	TaskToken interPacketGapCheckTimerTask;
	TaskToken qosMeasurementTimerTask;
	Boolean createReceivers;
	Boolean outputQuickTimeFile;
	Boolean generateMP4Format;
	QuickTimeFileSink* qtOut;
	Boolean outputAVIFile;
	AVIFileSink* aviOut;
	Boolean audioOnly;
	Boolean videoOnly;
	char const* singleMedium;
	int verbosityLevel; // by default, print verbose output
	double duration;
	double durationSlop; // extra seconds to play at the end
	double initialSeekTime;
	double scale;
	unsigned interPacketGapMaxTime;
	unsigned totNumPacketsReceived; // used if checking inter-packet gaps
	Boolean playContinuously;
	int simpleRTPoffsetArg;
	Boolean sendOptionsRequest;
	Boolean sendOptionsRequestOnly;
	Boolean oneFilePerFrame;
	Boolean notifyOnPacketArrival;
	Boolean streamUsingTCP;
	portNumBits tunnelOverHTTPPortNum;
	char* username;
	char* password;
	char* proxyServerName;
	unsigned short proxyServerPortNum;
	unsigned char desiredAudioRTPPayloadFormat;
	char* mimeSubtype;
	unsigned short movieWidth; // default
	Boolean movieWidthOptionSet;
	unsigned short movieHeight; // default
	Boolean movieHeightOptionSet;
	unsigned movieFPS; // default
	Boolean movieFPSOptionSet;
	char const* fileNamePrefix;
	unsigned fileSinkBufferSize;
	unsigned socketInputBufferSize;
	Boolean packetLossCompensate;
	Boolean syncStreams;
	Boolean generateHintTracks;
	unsigned qosMeasurementIntervalMS; // 0 means: Don't output QOS data
	unsigned statusCode;

	struct timeval startTime;

	qosMeasurementRecord* qosRecordHead;
	unsigned nextQOSMeasurementUSecs;

	void scheduleNextQOSMeasurement();

	//CIPCameraStreamReceiver
	Boolean allowProxyServers;
	Boolean controlConnectionUsesTCP;
	Boolean supportCodecSelection;
	char const* clientProtocolName;

	Medium* createClient(UsageEnvironment& env,
                     int verbosityLevel, char const* applicationName);
	char* getOptionsResponse(Medium* client, char const* url,
			 char* username, char* password);
	char* getSDPDescriptionFromURL(Medium* client, char const* url,
			       char const* username, char const* password,
			       char const* /*proxyServerName*/,
			       unsigned short /*proxyServerPortNum*/,
			       unsigned short /*clientStartPort*/);
	Boolean clientSetupSubsession(Medium* client, MediaSubsession* subsession,
			      Boolean streamUsingTCP);
	Boolean clientStartPlayingSession(Medium* client,
				  MediaSession* session);
	Boolean clientTearDownSession(Medium* client,
			      MediaSession* session);

	int videoInIndex;

	TaskScheduler* scheduler;
};
